// WndBinder.h: interface for the CWndBinder class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_WNDBINDER_H__F9BC50B9_F954_4144_8B10_F395DC8CA4CF__INCLUDED_)
#define AFX_WNDBINDER_H__F9BC50B9_F954_4144_8B10_F395DC8CA4CF__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

enum BIND_BORDER
{
	BIND_LEFT =	0x01,
	BIND_TOP =	0x02,
	BIND_RIGHT = 0x04,
    BIND_BOTTOM = 0x08
};

#define BIND_TOPLEFT		(BIND_LEFT|BIND_TOP)
#define BIND_TOPRIGHT		(BIND_RIGHT|BIND_TOP)
#define BIND_BOTTOMRIGHT	(BIND_RIGHT|BIND_BOTTOM)
#define BIND_BOTTOM_LEFT	(BIND_LEFT|BIND_BOTTOM)

#define BIND_TOP_TRIPLE		(BIND_LEFT|BIND_TOP|BIND_RIGHT)
#define BIND_LEFT_TRIPLE	(BIND_TOP|BIND_LEFT|BIND_BOTTOM)
#define BIND_RIGHT_TRIPLE	(BIND_TOP|BIND_RIGHT|BIND_BOTTOM)
#define BIND_BOTTOM_TRIPLE	(BIND_LEFT|BIND_BOTTOM|BIND_RIGHT)

#define BIND_ALL			(BIND_LEFT|BIND_TOP|BIND_RIGHT|BIND_BOTTOM)

enum BIND_TARGET
{
	NOT_BIND,
	PARENT_WND,
	SIBLING_WND,
	PARENT_WND_BORDER
};

struct BORDER_BIND_INFO
{
	BIND_TARGET Target;
	LONG* m_pBindData;
	int m_nOffset;
};

enum WND_BORDER
{
	LEFT_BORDER		=0,
	TOP_BORDER		=1,
	RIGHT_BORDER	=2,
	BOTTOM_BORDER	=3
};

struct WND_BIND_INFO
{
	BORDER_BIND_INFO m_BorderBindInfo[4];
	CRect m_rectWndOrigin;
	CRect m_rectWnd;
	HWND hWnd;
};

class CWndBinder  
{
	typedef map<HWND, WND_BIND_INFO> CWndBindMap;
private:
	CWnd* m_pParentWnd;
	CRect m_rectParentOrigin;
	CRect m_rectParent;
	CWndBindMap m_WndBindMap;

private:
	void InitBindInfo(WND_BIND_INFO* pBindInfo, HWND hWnd);

	WND_BIND_INFO* GetBindInfo(HWND hWnd);
	WND_BIND_INFO* AddBindInfo(HWND hWnd);

	WND_BIND_INFO* FindBindInfo(HWND hWnd);

	void CalcChildWndRectBindParent(WND_BIND_INFO* pBindInfo, const CRect& rectClient);
	void CalcChildWndRectBindParentBorder(WND_BIND_INFO* pBindInfo);
	void CalcChildWndRectBindChild(WND_BIND_INFO* pBindInfo);
	void CalcChildWndRectNotBind(WND_BIND_INFO* pBindInfo);

public:
	CWndBinder();
	virtual ~CWndBinder();

	void Reset();
	void SetParent(CWnd* pWnd);

	void BindChildToParent(int nChildID, DWORD dwBindBorder, bool bBindToBorder = false);
	void BindChildToParent(CWnd* pChild, DWORD dwBindBorder, bool bBindToBorder = false);
	void BindChildToParent(HWND hChild, DWORD dwBindBorder, bool bBindToBorder = false);

	void BindToParentBorder(int nChildID, WND_BORDER BindBorder, WND_BORDER TargetBorder);
	void BindToParentBorder(CWnd* pChild, WND_BORDER BindBorder, WND_BORDER TargetBorder);
	void BindToParentBorder(HWND hChild, WND_BORDER BindBorder, WND_BORDER TargetBorder);

	void BindToParentBorder(int nChildID);
	void BindToParentBorder(CWnd* pChild);
	void BindToParentBorder(HWND hChild);

	void BindChildToParent(int nFirstChildID, int nLastChildID, DWORD dwBindBorder);

	void BindChildToChild(int nChildID, WND_BORDER BindBorder, int nTargetID, WND_BORDER TargetBorder);
	void BindChildToChild(CWnd* pChild, WND_BORDER BindBorder, CWnd* pTarget, WND_BORDER TargetBorder);
	void BindChildToChild(HWND hChild, WND_BORDER BindBorder, HWND hTarget, WND_BORDER TargetBorder);

	void CancelBind(int nChildID, DWORD dwBindBorder);
	void CancelBind(CWnd* pChild, DWORD dwBindBorder);
	void CancelBind(HWND hChild, DWORD dwBindBorder);

	void RepositionChildWindows();

	void UpdateOriginHeight(HWND hChild, int nHeight);
};

#endif // !defined(AFX_WNDBINDER_H__F9BC50B9_F954_4144_8B10_F395DC8CA4CF__INCLUDED_)
